﻿using MvvmCross.Core.ViewModels;
using Sidvall.IdentityManager.UI.Entities;
using Sidvall.IdentityManager.UI.Messaging;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Input;

namespace Sidvall.IdentityManager.UI.ViewModels
{
    public class AppStartViewModel : Sidvall.UI.ViewModels.ViewModelBase
    {
        #region Public Members

        #region StartIsVisible

        private bool _StartIsVisible;
        public bool StartIsVisible
        {
            get
            {
                if (_PageType != null)
                    return (_PageType.Value == PageType.Start);
                return _StartIsVisible;
            }
            set
            {
                _StartIsVisible = value;
                RaisePropertyChanged("StartIsVisible");
            }
        }

        #endregion
        #region NewsIsVisible

        private bool _NewsIsVisible;
        public bool NewsIsVisible
        {
            get
            {
                if (_PageType != null)
                    return (_PageType.Value == PageType.News);
                return _NewsIsVisible;
            }
            set
            {
                _NewsIsVisible = value;
                RaisePropertyChanged("NewsIsVisible");
            }
        }

        #endregion
        #region ActiveServerItem

        public ServerItem ActiveServerItem
        {
            get
            {
                if (this.UserConfiguration == null)
                    return null;
                return (from o in this.UserConfiguration.ServerItems
                        where o.ServerItemId == Sidvall.IdentityManager.SystemContext.Current.ActiveServerItemId
                        select o).FirstOrDefault();
            }
        }

        #endregion
        #region UserConfiguration

        private UserConfiguration _UserConfiguration;
        public UserConfiguration UserConfiguration
        {
            get
            {
                return _UserConfiguration;
            }
            set
            {
                _UserConfiguration = value;
                RaisePropertyChanged("UserConfiguration");
            }
        }

        #endregion
        #region Created

        private string _Created;
        public string Created
        {
            get
            {
                return _Created;
            }
            set
            {
                _Created = value;
                RaisePropertyChanged("Created");
            }
        }

        #endregion
        #region Version

        private string _Version;
        public string Version
        {
            get
            {
                return _Version;
            }
            set
            {
                _Version = value;
                RaisePropertyChanged("Version");
            }
        }

        #endregion
        #region FileVersion

        private string _FileVersion;
        public string FileVersion
        {
            get
            {
                return _FileVersion;
            }
            set
            {
                _FileVersion = value;
                RaisePropertyChanged("FileVersion");
            }
        }

        #endregion
        #region WorkCaption

        private string _WorkCaption;
        public string WorkCaption
        {
            get
            {
                return _WorkCaption;
            }
            set
            {
                _WorkCaption = value;
                RaisePropertyChanged("WorkCaption");
            }
        }

        #endregion
        #region ProgressValue

        private double _ProgressValue;
        public double ProgressValue
        {
            get
            {
                return _ProgressValue;
            }
            set
            {
                _ProgressValue = value;
                RaisePropertyChanged("ProgressValue");
            }
        }

        #endregion
        #region NewsHtml

        private string _NewsHtml;
        public string NewsHtml
        {
            get
            {
                return _NewsHtml;
            }
            set
            {
                _NewsHtml = value;
                RaisePropertyChanged("NewsHtml");
            }
        }

        #endregion

        // Commands
        #region CloseNewsCommand

        public ICommand CloseNewsCommand
        {
            get
            {
                return new MvxCommand(CloseNews);
            }
        }

        #endregion
        #region CloseNews

        public void CloseNews()
        {
            ShowContent();
        }

        #endregion
        #region UnsubscribeToNewsCommand

        public ICommand UnsubscribeToNewsCommand
        {
            get
            {
                return new MvxCommand(async () => await UnsubscribeToNewsAsync());
            }
        }

        #endregion
        #region UnsubscribeToNewsAsync

        public async Task UnsubscribeToNewsAsync()
        {
            this.UserConfiguration.ShowNewsAtStartup = false;
            this.UserConfiguration = await Sidvall.IdentityManager.UI.SystemContext.Current.SaveUserConfigurationAsync(this.UserConfiguration, false);
            ShowContent();
        }

        #endregion

        #region StartAsync

        protected override async Task StartAsync()
        {
            List<System.Threading.Tasks.Task> tasks;

            _LoadContent = true;

            tasks = new List<System.Threading.Tasks.Task>();
            _PageType = null;
            this.NewsIsVisible = false;
            this.StartIsVisible = true;
            this.ProgressValue = 0;
            this.WorkCaption = "Load user settings...";
            tasks.Add(Sidvall.IdentityManager.UI.SystemContext.Current.LoadUserConfigurationAsync());
            tasks.Add(Sidvall.IdentityManager.SystemContext.Current.LoadVersionAsync());
            await System.Threading.Tasks.Task.WhenAll(tasks);
            this.UserConfiguration = Sidvall.IdentityManager.UI.SystemContext.Current.UserConfiguration;
            this.Version = Sidvall.IdentityManager.SystemContext.Current.Version;

            this.ProgressValue = 50;
            this.WorkCaption = "Connecting to server...";
            await Sidvall.IdentityManager.UI.SystemContext.Current.LoadServerInfoAsync(true, false);
            this.UserConfiguration = Sidvall.IdentityManager.UI.SystemContext.Current.UserConfiguration;

            this.ProgressValue = 70;
            this.WorkCaption = "Loading plugins";
            await Sidvall.SystemContext.Current.TypeCache.AddAssembliesAsync(this.UserConfiguration.PluginPath);
            await Sidvall.IdentityManager.UI.SystemContext.Current.InitializePluginsAsync();

            this.ProgressValue = 90;
            this.WorkCaption = "Checking tool version...";
            if (this.Version != Sidvall.IdentityManager.Configuration.SettingsManager.CurrentVersion)
            {
                if (!this.UserConfiguration.ShowNewsAtStartup)
                {
                    this.UserConfiguration.ShowNewsAtStartup = true;
                    this.UserConfiguration = await Sidvall.IdentityManager.UI.SystemContext.Current.SaveUserConfigurationAsync(this.UserConfiguration, false);
                }
                this.Version = await Sidvall.IdentityManager.SystemContext.Current.SaveVersionAsync(Sidvall.IdentityManager.Configuration.SettingsManager.CurrentVersion);
            }

            this.ProgressValue = 100;
            if (this.UserConfiguration.ShowNewsAtStartup)
            {
                _LoadContent = false;
                tasks = GetLoadTasks();
                await System.Threading.Tasks.Task.WhenAll(tasks);
                this.NewsHtml = await Sidvall.SystemContext.Current.SystemStorageManager.ReadAllTextAsync(@"Data\News.htm");
                this.NewsIsVisible = true;
                this.StartIsVisible = false;
            }
            else
            {
                _LoadContent = true;
            }
        }

        #endregion
        #region OnAfterStart

        protected override void OnAfterStart()
        {
            if (_LoadContent)
                ShowContent();
        }

        #endregion

        #endregion
        #region Private Members

        private PageType? _PageType = PageType.News;
        private enum PageType
        {
            Start,
            News,
        }
        private bool _LoadContent;

        // Tasks
        #region GetLoadTasks

        private List<Task> GetLoadTasks()
        {
            List<Task> tasks;

            tasks = new List<Task>();
            tasks.Add(LoadAssemblyTimestampAsync());
            tasks.Add(LoadAssemblyVersionAsync());
            return tasks;
        }

        #endregion
        #region LoadAssemblyTimestampAsync

        private async Task LoadAssemblyTimestampAsync()
        {
            var time = await Sidvall.SystemContext.Current.PackageManager.GetInstalledDateAsync();
            this.Created = time.ToString();
        }

        #endregion
        #region LoadAssemblyVersionAsync

        private async Task LoadAssemblyVersionAsync()
        {
            var version = await Sidvall.SystemContext.Current.PackageManager.GetVersionAsync();
            this.FileVersion = version.ToString();
        }

        #endregion

        #region ShowContent

        private void ShowContent()
        {
            UserConfigurationParameter parameter;

            Sidvall.UI.SystemContext.Current.ApplicationManager.Status = Sidvall.UI.ApplicationStatus.Started;
            if (this.ActiveServerItem.IsLoaded)
            {
                switch (this.UserConfiguration.StartPageId)
                {
                    case Sidvall.IdentityManager.Data.PageType.Users:
                        ShowViewModel<AspNetUsersCollectionViewModel>((object)null, true, "CenterContent");
                        break;
                    default:
                        ShowViewModel<DashboardViewModel>((object)null, true, "CenterContent");
                        break;
                }
            }
            else
            {
                parameter = new UserConfigurationParameter()
                {
                    ShowError = true,
                };
                ShowViewModel<UserConfigurationViewModel>(parameter, true, "CenterContent");
            }
        }

        #endregion

        #endregion
    }
}
